﻿/**
* 节点基类。
*/
Ext.define('Happy.designer.Node', {
    /**
     * @cfg {String} 节点的形状类型，可选的有：cycle、rect、eclipse 和 square。
     */
    shapeType: null,

    /**
     * @cfg {Object} 默认形状配置。
     */
    defaultShapeConfig: null,

    constructor: function (drawer, config) {
        var me = this;

        me.drawer = drawer;
        me.nodeId = config.nodeId;

        delete config.nodeId;

        me.initSprites(config);
    },

    /**
     * 初始化节点需要的原件。
     * 
     * @private
     * @param {Object} config
     */
    initSprites: function (config) {
        var me = this;

        me.drawer.surface.add(me.createSprites(config));

        me.group = me.drawer.surface.getGroup(me.nodeId);
        me.group.show(true);

        me.shape = me.group.getAt(0);

        me.text = me.group.getAt(1);

        me.cycles = me.drawer.surface.getGroup(me.nodeId + '-cycles');
        me.cycles.hide(true);
    },

    /**
     * 移动节点。
     * 
     * @public
     * @param {Number} dx x 坐标移动量
     * @param {Number} dy y 坐标移动量
     */
    move: function (dx, dy) {
        this.group.each(function (item) {
            item.setAttributes({
                x: item.attr.x + dx,
                y: item.attr.y + dy
            }, true);
        });
    },

    /**
     * 创建原件配置数组。
     * 
     * @private
     * @param {Object} config
     * @return {Array}
     */
    createSprites: function (config) {
        var me = this;

        var shape = me.createShape(config);
        var text = me.createText(shape, config);
        var cycles = me.createConnectorCycles(shape);

        return [shape, text].concat(cycles);
    },

    /**
     * 创建形状原件配置。
     * 
     * @private
     * @param {Object} config
     * @return {Object}
     */
    createShape: function (config) {
        var me = this;

        var rect = Ext.applyIf({
            type: me.shapeType,
            zIndex: 0,
            group: me.nodeId
        }, config);

        return Ext.applyIf(rect, me.defaultShapeConfig);
    },

    /**
     * 创建文本原件配置。
     * 
     * @private
     * @param {Object} shape 形状原件配置
     * @param {Object} config
     * @return {Object}
     */
    createText: function (shape, config) {
        var me = this;

        var text = config.text || "";
        var textSize = Ext.util.TextMetrics.measure(Ext.getBody(), text);
        var textXY = me.getTextXY(shape, textSize);

        return {
            type: "text",
            zIndex: 0,
            nodeId: me.nodeId,
            group: me.nodeId,
            text: text,
            font: config.font || "13px helvetica",
            x: textXY.x,
            y: textXY.y,
            width: textSize.width,
            height: textSize.height
        };
    },

    /**
     * 返回文本原件的坐标。
     * 
     * @private
     * @param {Object} shape 形状原件配置
     * @param {Object} textSize 文本尺寸
     * @return {Object}
     */
    getTextXY: function (shape, textSize) {
        var me = this;

        var shapeBox = me.getShapeBox(shape);

        return {
            x: shapeBox.x + (shapeBox.width - textSize.width) / 2,
            y: shapeBox.y + shapeBox.height / 2
        };
    },

    /**
     * 返回形状原件的盒子配置。
     * 
     * @protect
     * @param {Object} shape 形状原件配置
     * @return {Object}
     */
    getShapeBox: Ext.emptyFun,

    /**
     * 返回连接圆形原件配置数组。
     * 
     * @private
     * @param {Object} shape 形状原件配置
     * @return {Object}
     */
    createConnectorCycles: function (shape) {
        var me = this;

        var shapeBox = me.getShapeBox(shape);

        var defaultConfig = {
            zIndex: 1,
            type: 'circle',
            nodeId: me.nodeId,
            group: [me.nodeId, me.nodeId + '-cycles'],
            fill: '#FFF',
            stroke: '#000',
            'stroke-width': 1,
            radius: 6
        };

        return [
            Ext.apply({
                x: shapeBox.x,
                y: shapeBox.y + shapeBox.height / 2,
                position: 'left'
            }, defaultConfig),
            Ext.apply({
                x: shapeBox.x + shapeBox.width / 2,
                y: shapeBox.y + shapeBox.height,
                position: 'bottom'
            }, defaultConfig),
            Ext.apply({
                x: shapeBox.x + shapeBox.width,
                y: shapeBox.y + shapeBox.height / 2,
                position: 'right'
            }, defaultConfig),
            Ext.apply({
                x: shapeBox.x + shapeBox.width / 2,
                y: shapeBox.y,
                position: 'top'
            }, defaultConfig)
        ];
    }
});